package com.example.demo.flux.controller;

import com.example.demo.flux.client.DemoClient;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.reactive.function.client.WebClient;
import reactor.core.publisher.Mono;
import reactor.core.scheduler.Schedulers;

import java.util.Objects;
import java.util.concurrent.atomic.AtomicInteger;

@RestController
@RequestMapping("/demo")
public class DemoController {

    private final DemoClient demoClient;

    public DemoController(DemoClient demoClient) {
        this.demoClient = demoClient;
    }

    private static ThreadLocal<String> timeString = new ThreadLocal<>();
    private static AtomicInteger number = new AtomicInteger(0);

    @GetMapping("hi")
    public Mono<String> sayHello(String name) {
        timeString.set(String.valueOf(number.getAndAdd(1)) + " ");
        System.out.println(timeString.get() + Thread.currentThread().getName());
        Mono<String> mono;
        if (Objects.equals("???", name)) {
            throw new UnsupportedOperationException("I don't known " + name);
        } else if (Objects.equals("remote", name)) {
            mono = Mono.create(callBack -> {
                try {
                    callBack.success(demoClient.remoteHi(name));
                } catch (Exception exp) {
                    callBack.error(exp);
                }
            });
        } else if (Objects.equals("slow", name)) {
            WebClient webClient = WebClient.create();
            mono = webClient.get()
                    .uri("http://localhost:8080/demo/slowCall?name=" + name + timeString.get())
                    .exchangeToMono(cr -> cr.bodyToMono(String.class)
                            .map(r -> timeString.get() + " "  + Thread.currentThread().getName() + r));
//            mono = Mono.<String>create(callBack -> {
//                try {
//                    callBack.success(demoClient.slowCall(name));
//                } catch (Exception exp) {
//                    callBack.error(exp);
//                }
//            }).subscribeOn(Schedulers.boundedElastic());
        } else {
            mono = Mono.create(callBack -> {
                callBack.success("Hi " + name + ", time is " + timeString.get() + Thread.currentThread().getName());
            });
        }
        return mono;
    }

    @GetMapping("slowCall")
    public ResponseEntity<String> slowCall(@RequestParam(name = "name") String name) {
        try {
            Thread.sleep(10000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return ResponseEntity.status(200).body("Slow Hi " + name);
    }

    @GetMapping("status")
    public ResponseEntity<String> remoteHi(@RequestParam(name = "name") String name) {
        return ResponseEntity.status(404).body("Remote Hi " + name);
    }
}
